package com.eati.cm.hook_like;

import com.eati.cm.excp.DesignFaultExcp;
import com.eati.cm.utils.CastUtil;
import com.eati.cm.utils.IOUtil;
import com.eati.cm.view.IResult;
import com.eati.cm.view.Result;
import com.eati.cm.view.ResultStatus;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.istack.NotNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.NonNullApi;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.Date;

@RestControllerAdvice
public class UnifiedRespHandler implements ResponseBodyAdvice<Object> {
    @Value("${server.servlet.context-path:}")
    private String contextPath;

    @Override
    public boolean supports(@NotNull MethodParameter returnType, @NotNull Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, @NotNull MethodParameter returnType, @NotNull MediaType selectedContentType,
                                  @NotNull Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  @NotNull ServerHttpRequest request, @NotNull ServerHttpResponse response) {
    	
        // 若擬返回值爲IResult則放行。
        if(body instanceof IResult){
            return body;
        }

        // 禁止返回POD類型
        if(body instanceof String
           || body instanceof Integer
           || body instanceof Boolean
           || body instanceof Long){
            try {
                throw new DesignFaultExcp("禁止返回POD! class=" + body.getClass());
            } catch (DesignFaultExcp e) {
                e.printStackTrace();
                Result<Object> res = new Result<>();
                res.status = ResultStatus.PROG_DESIGN_FAULT;
                res.finishedDate = new Date();
                res.opMsg = e;
                res.opMsgType = e.getClass().toString();
                try {
                    return CastUtil.toJson(res);
                } catch (JsonProcessingException jsonProcessingException) {
                    jsonProcessingException.printStackTrace();
                    return "{data: \"\", finishedDate: \"\", " +
                            "status: \"PROG_ERR\", opMsg: \"序列化控制器返回值" +
                            "時遇到錯誤。\"}";
                }
            }
        }

        // 否則，包裝爲Result。
        //try {
            Result<Object> res = new Result<>();
            res.data = body;
            res.status = ResultStatus.SUCC;
            res.finishedDate = new Date();
            /*return new ObjectMapper().writeValueAsString(
                    res
            );*/

            return res;
        /*} catch (JsonProcessingException e) {
            e.printStackTrace();
            return "{data: \"\", finishedDate: \"\", " +
                    "status: \"PROG_ERR\", opMsg: \"序列化控制器返回值" +
                    "時遇到錯誤。\"}";
        }*/
    }
}
